API: Coerce None according to the dtype of the container

This pull request fixes #7939 by ensuring that None coercion always obeys the following rules:

1. If the container is numeric, None should be coerced to NaN
2. If the container is for time data, None should be coerced to NaT
3. If the container contains heterogenous data (i.e. objects), None should be preserved.

## Old behaviour examples

### Assigning None in integer containers
None is sometimes preserved, sometimes coerced to NaN, and sometimes causes an error.

```python
>>> s = Series([1, 2, 3])
>>> s[0] = None # error

>>> s = Series([1, 2, 3])
>>> s.loc[0] = None
>>> s
0    None
1       2
2       3
dtype: object

>>> s = Series([1, 2, 3])
>>> s[s == 1] = None
>>> s
0   NaN
1     2
2     3
dtype: float64

>>> s = Series([1, 2, 3])
>>> s.loc[s == 1] = None
0    None
1       2
2       3
dtype: object

```

Datetimes are similar.

### Assigning None in object containers
None is sometimes preserved, and sometimes coerced.

```python
>>> s = Series(["a", "b", "c"])
>>> s[0] = None
0    None
1       b
2       c
dtype: object

>>> s = Series(["a", "b", "c"])
>>> s.loc[0] = None
0    None
1       b
2       c
dtype: object

>>> s = Series(["a", "b", "c"])
>>> s[s == 'a'] = None
0    NaN
1      b
2      c
dtype: object

>>> s = Series(["a", "b", "c"])
>>> s.loc[s == 'a'] = None
0    None
1       b
2       c
dtype: object
```

## New behaviour examples

### None is always coerced to NaN in integer containers

```python
>>> s = Series([1, 2, 3])
>>> s[0] = None
0    NaN
1      2
2      3
dtype: float64

>>> s = Series([1, 2, 3])
>>> s.loc[0] = None # same

>>> s = Series([1, 2, 3])
>>> s[s == 1] = None # same

>>> s = Series([1, 2, 3])
>>> s.loc[s == 1] = None # same
```

### None is always preserved in object containers

```python
>>> s = Series(["a", "b", "c"])
>>> s[0] = None
0    None
1       b
2       c
dtype: object

>>> s = Series(["a", "b", "c"])
>>> s.loc[0] = None # same

>>> s = Series(["a", "b", "c"])
>>> s[s == 'a'] = None

>>> s = Series(["a", "b", "c"])
>>> s.loc[s == 'a'] = None # same
```
how about you add an option to ``array_equivalent``, maybe ``strict=False``? or something to avoid repeated code