so... like in c++?
Generally "strong" vs "weak" typing[1] is an ill-defined an mostly useless definition.
[1] as opposed to static vs dynamic or safe vs unsafe.
edit: I guess what you want to say is that implicit casts make a type system weak. But even there there is plenty of wiggle room: I think that everybody agree that implicitly converting the string "1" to an integer is bad (which is not allowed in C++). Narrowing conversions are arguably bad (they are sometimes allowed in C++), but some other implicit conversions are hard to argue against (int to long for example, or derived to base).
For dynamic types, sure, that's a reasonable enough definition. But it doesn't really make sense for static types: they're attached to expressions in your source code, not runtime values.
In order to have that, you need static typing of variables and constants, like most statically typed imperative languages have. But you also need a method to specify required input types and expected output types of all functions.
In a purely functional language like Haskell where there are only functions, and functions are first class and can be both inputs to or outputs from other functions, then the entire operation of the program is encapsulated in its function type signatures.
The entire flow of data and logic through the program can be type-checked by the compiler, and function implementations checked against their type signatures.
Usually: A strong type system does not allow types to change after being established. A weak type system allows types to change. This is also described in the original article.