Fix memory leak with ujson module
- [X] closes #49222 (Replace xxxx with the GitHub issue number)

This is mostly vendored from ujson upstream

https://github.com/ultrajson/ultrajson/blob/main/python/ujson.c

Using a static PyObject the way we did before is strongly discouraged. This is more verbose but should be more correct, although interestingly pushes us back to the legacy module initialization instead of PEP 489 multi phase initialization


@JelleZijlstra if you have the ability to confirm this patch fixes your issue would be appreciated As an aside, has Pandas considered https://github.com/ijl/orjson (a Rust-based JSON (de)serializer)? Its a pretty small memory leak. I don't think it would even register on a peakmem ASV. Let's see if it helps @jellezijlstra and can go from there Looks good @WillAyd. Would be good to have a whatsnew note for this then LGTM  Thanks @WillAyd  This patch may have induced a potential regression. Please check the links below. If any ASVs are parameterized, the combinations of parameters that a regression has been detected appear as subbullets. This is a partially automated message.

 - https://asv-runner.github.io/asv-collection/pandas/#io.json.ToJSON.time_to_json
   - orient='split'; frame='df_int_float_str'
   - orient='split'; frame='df_int_floats'
   - orient='split'; frame='df_td_int_ts'
   - orient='values'; frame='df_int_float_str'
   - orient='values'; frame='df_int_floats'
   - orient='values'; frame='df_td_int_ts'
 - https://asv-runner.github.io/asv-collection/pandas/#io.json.ToJSONWide.time_to_json
   - orient='split'; frame='df_int_floats'
   - orient='split'; frame='df_td_int_ts'
   - orient='values'; frame='df_int_float_str'
   - orient='values'; frame='df_int_floats'
   - orient='values'; frame='df_td_int_ts'