2. They must be exhaustive (a few tests here or there wont help much)
Not necessarily. Sometimes you can get a lot of mileage out of a very few tests. If you test composite functionality that involves many modules, you can get reasonable coverage from a small number of high-level tests. Strictly speaking that's not unit testing, even if you do use a unit testing framework for it, but it works, so who cares what it's called.
Even if you have lots of tests and they are well maintained and correct, it still pretty much guaranteed that not all edge cases would be covered
Edge case errors are rarely type errors. The way to catch edge case errors is by having unit tests, regardless of language. And of course, by writing clean code that doesn't have too many special cases in the first place.
The people most likely to skip unit testing are the people who trust the static type checker too much.
I like Python and it is usually my language of choice for scripting (mostly because of a large variety of libraries available), but for a large and complex codebase I would rather choose something more strictly typed
I don't know what you call large, but I'm quite comfortable working with 100K SLOC Python applications.
It does take discipline, but then writing large applications takes discipline in any language, and I'm not convinced that it takes more discipline to write a 100K Python program than it takes to write the 300K C# program with the equivalent functionality.