diff --git a/pydantic/generics.py b/pydantic/generics.py
--- a/pydantic/generics.py
+++ b/pydantic/generics.py
@@ -62,7 +62,11 @@ def __class_getitem__(cls: Type[GenericModelT], params: Union[Type[Any], Tuple[T
             returned as is.
 
         """
-        cached = _generic_types_cache.get((cls, params))
+
+        def _cache_key(_params: Any) -> Tuple[Type[GenericModelT], Any, Tuple[Any, ...]]:
+            return cls, _params, get_args(_params)
+
+        cached = _generic_types_cache.get(_cache_key(params))
         if cached is not None:
             return cached
         if cls.__concrete__ and Generic not in cls.__bases__:
@@ -128,9 +132,9 @@ def __class_getitem__(cls: Type[GenericModelT], params: Union[Type[Any], Tuple[T
 
         # Save created model in cache so we don't end up creating duplicate
         # models that should be identical.
-        _generic_types_cache[(cls, params)] = created_model
+        _generic_types_cache[_cache_key(params)] = created_model
         if len(params) == 1:
-            _generic_types_cache[(cls, params[0])] = created_model
+            _generic_types_cache[_cache_key(params[0])] = created_model
 
         # Recursively walk class type hints and replace generic typevars
         # with concrete types that were passed.

Yep it's a bug. Since for python `Union[int, float] == Union[float, int]`, the key in the cache is the same.
I guess we could use `(cls, params, get_args(params))` as key of `_generic_types_cache` instead of `(cls, params)`
> Yep it's a bug. Since for python `Union[int, float] == Union[float, int]`, the key in the cache is the same.

Good to hear!

> I guess we could use `(cls, params, get_args(params))` as key of `_generic_types_cache` instead of `(cls, params)`

What about nested models, say `List[Union[float, int]]` and `List[Union[int, float]]`? Wouldn’t these still be considered equal? 
Is this new in v1.10?
> Is this new in v1.10?

No, saw it first in 1.9.0 and then updated to check if it was still there in the newest version. It is probably as old as the current specification of the key in `_generic_types_cache`.
Humm, can't remember if that was new in 1.9 or 1.8.

The question is whether we should fix this in a patch release of 1.10 or wait for V2?
> The question is whether we should fix this in a patch release of 1.10 or wait for V2?

That’s obviously not for me to say, but personally I think it would have been nice with a patch of at least the basic (non-nested) case, as the bug is breaking several of my tests.
This gets more complicated, as the more-or-less exact same issue is present in the `typing` library itself, e.g.

```python
from typing import get_args, List, Union

print(get_args(Union[int, float]))
print(get_args(Union[float, int]))
print(get_args(List[Union[float, int]]))
print(get_args(List[Union[int, float]]))
```

Prints:

```
(<class 'int'>, <class 'float'>)
(<class 'float'>, <class 'int'>)
(typing.Union[float, int],)
(typing.Union[float, int],)
```

This is discussed in [this CPython issue](https://github.com/python/cpython/issues/86483), which include comments by Guido, and which resulted in the following documentation change:

> If X is a union or [Literal](https://docs.python.org/3/library/typing.html#typing.Literal) contained in another generic type, the order of (Y, Z, ...) may be different from the order of the original arguments [Y, Z, ...] due to type caching.

(from the [current Python docs](https://docs.python.org/3/library/typing.html#typing.get_args))

This at least rules out a recursive solution using `get_args` for nested models (which I was toying around with). If I understand this correctly, I believe it also means that the difference between e.g. `List[Union[float, int]]` and `List[Union[int, float]]` would be inaccessible in Python itself, which is a problem.

Thinking from the perspective of a downstream library depending on `pydantic` I suppose one could implement a workaround for the nested problem(i.e. `List[Union[int, float]] == List[Union[float, int]]`) by replacing `Union` with a custom model, say `OrderedUnion`, which overrides `__eq__`. Such a model could even be included in `pydantic` if there is great enough need for this.

However, all of this does not disqualify the simple `get_args` fix suggested by @PrettyWood. It would still work for the top level `Union` case, as in my example code, which is really the only thing I need for my code anyway. Also, I suppose the fact that a solution to the nested problem would be dependent on the above-mentioned "feature" in Python is really an argument for only solving the simple non-nested issue now. So, in a sense, I would argue that this complication might actually make this issue simpler to manage, at least for now.
Confirmed, I think we should fix this in V1.10.

PR welcome, it'll need to be pretty quick to make it into the next patch release #4472, but otherwise it can be included in the (inevitable) next patch release.
I can give it a try.
great, thanks.
I'm getting the following mypy errors:
```
pydantic/generics.py:65: error: Argument 1 to "get_args" has incompatible type "Union[Type[Any], Tuple[Type[Any], ...]]"; expected "Type[Any]"  [arg-type]
pydantic/generics.py:131: error: Argument 1 to "get_args" has incompatible type "Tuple[Type[Any], ...]"; expected "Type[Any]"  [arg-type]
```

Which seems to be a bug in mypy: https://github.com/python/mypy/issues/4625

Any thoughts on how to handle this?
hard without seeing the change, create the PR so I can see it.
Basically, the type of the `params` parameter specified in `GenericModel.__class_getitem__` is incompatible with the `Type[Any]` in the `get_args` method, according to `mypy`. As far as I can understand, `Type[Any]` is supposed to allow any type, including `Union` and `Tuple`. It makes sense to me that this is a mypy bug, but I might have misread the mypy issue, as the issue is not exactly the same.

Anyway, I'll add a test and submit the PR for you to see.
I'd love to include this fix in v1.10.2, any chance you can submit the PR asap so I can review and merge it?
diff --git a/tests/test_generics.py b/tests/test_generics.py
--- a/tests/test_generics.py
+++ b/tests/test_generics.py
@@ -688,6 +688,52 @@ class Model(BaseModel):  # same name, but type different, so it's not in cache
         assert globals()['MyGeneric[Model]__'] is third_concrete
 
 
+def test_generic_model_caching_detect_order_of_union_args_basic(create_module):
+    # Basic variant of https://github.com/pydantic/pydantic/issues/4474
+    @create_module
+    def module():
+        from typing import Generic, TypeVar, Union
+
+        from pydantic.generics import GenericModel
+
+        t = TypeVar('t')
+
+        class Model(GenericModel, Generic[t]):
+            data: t
+
+        int_or_float_model = Model[Union[int, float]]
+        float_or_int_model = Model[Union[float, int]]
+
+        assert type(int_or_float_model(data='1').data) is int
+        assert type(float_or_int_model(data='1').data) is float
+
+
+@pytest.mark.skip(
+    reason="""
+Depends on similar issue in CPython itself: https://github.com/python/cpython/issues/86483
+Documented and skipped for possible fix later.
+"""
+)
+def test_generic_model_caching_detect_order_of_union_args_nested(create_module):
+    # Nested variant of https://github.com/pydantic/pydantic/issues/4474
+    @create_module
+    def module():
+        from typing import Generic, List, TypeVar, Union
+
+        from pydantic.generics import GenericModel
+
+        t = TypeVar('t')
+
+        class Model(GenericModel, Generic[t]):
+            data: t
+
+        int_or_float_model = Model[List[Union[int, float]]]
+        float_or_int_model = Model[List[Union[float, int]]]
+
+        assert type(int_or_float_model(data=['1']).data[0]) is int
+        assert type(float_or_int_model(data=['1']).data[0]) is float
+
+
 def test_get_caller_frame_info(create_module):
     @create_module
     def module():

First instantiation of generic Union model defines type coercion of models instantiated later
### Initial Checks

- [X] I have searched GitHub for a duplicate issue and I'm sure this is something new
- [X] I have searched Google & StackOverflow for a solution and couldn't find anything
- [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io) and still think this is a bug
- [X] I am confident that the issue is with pydantic  (not my code, or another library in the ecosystem like [FastAPI](https://fastapi.tiangolo.com) or [mypy](https://mypy.readthedocs.io/en/stable))


### Description

When pydantic generic models are instantiated with Unions, the order of a particular set of types are fixed by the first instantiation, e.g.:

```python
from typing import Generic, TypeVar, Union

from pydantic.generics import GenericModel

NumberT = TypeVar('NumberT')


class NumberModel(GenericModel, Generic[NumberT]):
    data: NumberT


FloatOrIntModel = NumberModel[Union[float, int]]
print(FloatOrIntModel(data='1').data)

IntOrFloatModel = NumberModel[Union[int, float]]
print(IntOrFloatModel(data='1').data)
```
prints
```
1.0
1.0
```
While changing the order of the instantiations changes type coercion of both models:
```
1
1
```

In pydantic, type coercion of Union models depends on the order of the types. However, as explained in the documentation on [Unions](https://pydantic-docs.helpmanual.io/usage/types/#unions):

> typing.Union also ignores order when [defined](https://docs.python.org/3/library/typing.html#typing.Union), so Union[int, float] == Union[float, int] which can lead to unexpected behaviour when combined with matching based on the Union type order inside other type definitions

I think this should be considered a bug in pydantic, even though the user is warned against 'unexpected behaviour' combined with other code that depend on Union type equality. The unexpected behaviour in this case is caused by pydantic itself, there is no "matching based on the Union type order inside other type definitions" in the example code, nor are any third-party code imported. It is not difficult to envision situations where this dependency could cause very hard-to-find bugs.

It seems the cause of the error is the `_generic_types_cache` in `generics.py`, which caches the first Union model and uses this as the blueprint of later matching models (i.e. with the same set of types).

Setting `smart_union` to `True` has no impact.

Related to https://github.com/pydantic/pydantic/issues/2835.

### Example Code

_No response_

### Python, Pydantic & OS Version

```Text
pydantic version: 1.10.1
            pydantic compiled: True
                 install path: /Users/sveinugu/Library/Caches/pypoetry/virtualenvs/unifair-myuXak-6-py3.10/lib/python3.10/site-packages/pydantic
               python version: 3.10.4 | packaged by conda-forge | (main, Mar 24 2022, 17:42:03) [Clang 12.0.1 ]
                     platform: macOS-11.2.3-arm64-arm-64bit
     optional deps. installed: ['typing-extensions']
```


### Affected Components

- [ ] [Compatibility between releases](https://pydantic-docs.helpmanual.io/changelog/)
- [X] [Data validation/parsing](https://pydantic-docs.helpmanual.io/usage/models/#basic-model-usage)
- [ ] [Data serialization](https://pydantic-docs.helpmanual.io/usage/exporting_models/) - `.dict()` and `.json()`
- [ ] [JSON Schema](https://pydantic-docs.helpmanual.io/usage/schema/)
- [ ] [Dataclasses](https://pydantic-docs.helpmanual.io/usage/dataclasses/)
- [ ] [Model Config](https://pydantic-docs.helpmanual.io/usage/model_config/)
- [X] [Field Types](https://pydantic-docs.helpmanual.io/usage/types/) - adding or changing a particular data type
- [ ] [Function validation decorator](https://pydantic-docs.helpmanual.io/usage/validation_decorator/)
- [X] [Generic Models](https://pydantic-docs.helpmanual.io/usage/models/#generic-models)
- [ ] [Other Model behaviour](https://pydantic-docs.helpmanual.io/usage/models/) - `construct()`, pickling, private attributes, ORM mode
- [ ] [Settings Management](https://pydantic-docs.helpmanual.io/usage/settings/)
- [ ] [Plugins](https://pydantic-docs.helpmanual.io/) and integration with other tools - mypy, FastAPI, python-devtools, Hypothesis, VS Code, PyCharm, etc.

tests/test_generics.py::test_generic_model_caching_detect_order_of_union_args_basic
tests/test_generics.py::test_generic_name tests/test_generics.py::test_double_parameterize_error tests/test_generics.py::test_value_validation tests/test_generics.py::test_methods_are_inherited tests/test_generics.py::test_config_is_inherited tests/test_generics.py::test_default_argument tests/test_generics.py::test_default_argument_for_typevar tests/test_generics.py::test_classvar tests/test_generics.py::test_non_annotated_field tests/test_generics.py::test_must_inherit_from_generic tests/test_generics.py::test_parameters_placed_on_generic tests/test_generics.py::test_parameters_must_be_typevar tests/test_generics.py::test_subclass_can_be_genericized tests/test_generics.py::test_parameter_count tests/test_generics.py::test_cover_cache tests/test_generics.py::test_generic_config tests/test_generics.py::test_enum_generic tests/test_generics.py::test_generic tests/test_generics.py::test_alongside_concrete_generics tests/test_generics.py::test_complex_nesting tests/test_generics.py::test_required_value tests/test_generics.py::test_optional_value tests/test_generics.py::test_custom_schema tests/test_generics.py::test_child_schema tests/test_generics.py::test_custom_generic_naming tests/test_generics.py::test_nested tests/test_generics.py::test_partial_specification tests/test_generics.py::test_partial_specification_with_inner_typevar tests/test_generics.py::test_partial_specification_name tests/test_generics.py::test_partial_specification_instantiation tests/test_generics.py::test_partial_specification_instantiation_bounded tests/test_generics.py::test_typevar_parametrization tests/test_generics.py::test_multiple_specification tests/test_generics.py::test_generic_subclass_of_concrete_generic tests/test_generics.py::test_generic_model_pickle tests/test_generics.py::test_generic_model_from_function_pickle_fail tests/test_generics.py::test_generic_model_redefined_without_cache_fail tests/test_generics.py::test_get_caller_frame_info tests/test_generics.py::test_get_caller_frame_info_called_from_module tests/test_generics.py::test_get_caller_frame_info_when_sys_getframe_undefined tests/test_generics.py::test_iter_contained_typevars tests/test_generics.py::test_nested_identity_parameterization tests/test_generics.py::test_replace_types tests/test_generics.py::test_replace_types_with_user_defined_generic_type_field tests/test_generics.py::test_replace_types_identity_on_unchanged tests/test_generics.py::test_deep_generic tests/test_generics.py::test_deep_generic_with_inner_typevar tests/test_generics.py::test_deep_generic_with_referenced_generic tests/test_generics.py::test_deep_generic_with_referenced_inner_generic tests/test_generics.py::test_deep_generic_with_multiple_typevars tests/test_generics.py::test_deep_generic_with_multiple_inheritance tests/test_generics.py::test_generic_with_referenced_generic_type_1 tests/test_generics.py::test_generic_with_referenced_nested_typevar tests/test_generics.py::test_generic_with_callable tests/test_generics.py::test_generic_with_partial_callable tests/test_generics.py::test_generic_recursive_models tests/test_generics.py::test_generic_enum tests/test_generics.py::test_generic_literal tests/test_generics.py::test_generic_enums tests/test_generics.py::test_generic_with_user_defined_generic_field tests/test_generics.py::test_generic_annotated tests/test_generics.py::test_generic_subclass tests/test_generics.py::test_generic_subclass_with_partial_application tests/test_generics.py::test_multilevel_generic_binding tests/test_generics.py::test_generic_subclass_with_extra_type tests/test_generics.py::test_multi_inheritance_generic_binding tests/test_generics.py::test_parse_generic_json