Singleton metaclass for each argument set compatible with Pickle
The point of having to define either neither or both of __init__ and __reduce_ex__ is to set _args.
However you can just set _args in __call__ and then use the one you've set in your __reduce_ex__.
Note: untested
class ArgumentSingleton(type):
    __INSTANCES = {}

    def __new__(cls, name, bases, class_dict):
        def __reduce_ex__(self, protocol):
            return partial(type(self), *self.__args, **self.__kwargs), ()

        def __init__(self, *args, **kwargs):
            pass

        class_dict.setdefault('__init__', __init__)
        class_dict.setdefault('__reduce_ex__', __reduce_ex__)
        return super().__new__(cls, name, bases, class_dict)

    def __call__(cls, *args, **kwargs):
        key = (cls, args, frozendict(kwargs))
        if None is (self := cls.__INSTANCES.get(key)):
            self = cls.__INSTANCES[key] = super().__call__(cls, *args, **kwargs)
            self.__args, self.__kwargs = key[1:]
        return self

Now we should be able to see we can just stop defining a metaclass by;

changing __call__ to __new__, and
defining a default __reduce_ex__ on the base class.

from frozendict import frozendict
from functools import partial

class Singleton:
    __INSTANCES = {}

    def __new__(cls, *args, **kwargs):
        key = (cls, args, frozendict(kwargs))
        if None is (self := cls.__INSTANCES.get(key)):
            self = cls.__INSTANCES[key] = super().__new__(cls)
            self.__args, self.__kwargs = key[1:]
        return self

    def __reduce_ex__(self, protocol: int):
        return partial(type(self), *self.__args, **self.__kwargs), ()

class A(Singleton):
    pass


# passes all your tests and the following one
a = A(&quot;hi&quot;)
b = pickle.loads(pickle.dumps(a))
assert a is b