The idea does in fact comes from Cantor's Diagonal Argument. Recall how that argument works, if $f_n$ is a sequence of binary sequences then defining $f(n)=1-f_n(n)$ ensures that for every $n$, $f\neq f_n$.
Now given a class of functions (of any sort) with a common domain, if we can enumerate them using their domain, then defining $f(x)=f_x(x)+[\ldots]$ assures us that $f$ is not in that class of functions (where $\ldots$ is some reasonable and permitted operation, like adding $1$ or so).
Let me quote the second paragraph of Section $3.5$:
For concreteness, let us say that "diagonalization" is any technique that relies upon the following properties of Turing machines:
- The existence of an effective representations of Turing machines by strings.
- The ability of one TM to simulate any other without much overhead in running time or space.
This really just says that there is a way to encode Turing machines into strings of integers, and equally a natural number, and there is a Turing machine which takes an input of two numbers, decodes (if possible) the first one into a Turing machine, and simulate that machine when given the second number as an input.
So in fact we can think of Turing machines as natural numbers, and therefore we can index and input Turing machines to other Turing machines. So the above idea of diagonalization works. (Of course, since this topic is more about complexity of runtime you have to worry about the overheads, but as the second point in the excerpt says, that this is not a real worry.)